﻿#region Using Statements
using System;
using System.Collections.Generic;
using System.Text;
using starLiGHT.Collision;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
#endregion

namespace starLiGHT.Sandbox.Collision
{
    public class TextureObject : ICollidable2D
    {
        public event EventHandler Moved;

        private CircleF boundingCircle;
        private RectangleF boundingRectangle;
        private bool worldRectDirty = true;
        private RectangleF worldRect;
        private OrientedRectangleF orientedRectangle;
        private Texture2D texture;
        private Transform2D transform;

        public TextureObject(Vector2 position, Texture2D texture)
            : this(position, texture, false)
        {
        }

        public TextureObject(Vector2 position, Texture2D texture, Boolean boundingBoxFromTextureAlpha)
        {
            this.texture = texture;

            if (boundingBoxFromTextureAlpha)
            {
                //TODO: looks like here's something wrong...

                float minX = float.MaxValue;
                float maxX = float.MinValue;
                float minY = float.MaxValue;
                float maxY = float.MinValue;

                Color[] colors = new Color[texture.Width * texture.Height];
                texture.GetData<Color>(colors);

                for (int x = 0; x < texture.Width; x++)
                {
                    for (int y = 0; y < texture.Height; y++)
                    {
                        if (colors[y * texture.Width + x].A != 0f)
                        {
                            minX = MathHelper.Min(minX, x);
                            maxX = MathHelper.Max(maxX, x + 1);
                            minY = MathHelper.Min(minY, y);
                            maxY = MathHelper.Max(maxY, y + 1);
                        }
                    }
                }

                boundingRectangle = new RectangleF(new Vector2(minX, minY), maxX - minX, maxY - minY);
                //boundingRectangle.Center = position;
            }
            else
            {
                boundingRectangle = new RectangleF(Vector2.Zero, texture.GetSize());
            }

            transform = new Transform2D(position, texture.CenterOrigin());
            transform.Changed += new EventHandler<EventArgs>(transform_Changed);
            orientedRectangle = new OrientedRectangleF(boundingRectangle);
            boundingCircle = new CircleF(boundingRectangle);
        }

        void transform_Changed(object sender, EventArgs e)
        {
            worldRectDirty = true;
            if (Moved != null)
            {
                Moved(sender, e);
            }
        }

        public RectangleF LocalBoundingRectangle
        {
            get { return boundingRectangle; }
        }

        public RectangleF WorldBoundingRectangle
        {
            get
            {
                if (worldRectDirty)
                {
                    worldRect = boundingRectangle;
                    worldRect.Center = Vector2.Transform(boundingRectangle.Center, transform.TransformationMatrix);
                    worldRectDirty = false;
                }

                return worldRect;
            }
        }

        public CircleF BoundingCircle
        {
            get { return boundingCircle; }
        }

        public Transform2D Transform
        {
            get { return transform; }
            set { transform = value; }
        }

        public Vector2 Position
        {
            get { return transform.Position.HasValue ? transform.Position.Value : Vector2.Zero; }
            set
            {
                if ((transform.Position.HasValue ? transform.Position.Value : Vector2.Zero) != value)
                {
                    transform.Position = value;
                }
            }
        }

        // circle cannot rotate
        public float Orientation
        {
            get { return transform.Orientation; }
            set 
            {
                if (transform.Orientation != value)
                {
                    transform.Orientation = value;
                    orientedRectangle.Rotation = transform.Orientation;
                    boundingRectangle = orientedRectangle.ToRectangleF();
                    boundingCircle = new CircleF(boundingRectangle);
                }
            }
        }

        // always the same size for now
        public Vector2 Scale
        {
            get { return (transform.Scale.HasValue ? transform.Scale.Value : Vector2.One); }
        }

        public Texture2D Texture
        {
            get { return texture; }
        }

        public bool Colliding
        {
            get;
            set;
        }

        public bool Static
        {
            get;
            set;
        }

        public Hull2D Hull
        {
            get { return null; }
        }

        public Vector2 Velocity
        {
            get;
            set;
        }

        public object Tag
        {
            get;
            set;
        }

        public void LookAt(Vector2 target)
        {
            Vector2 dir = target - Position;
            Orientation = (float)Math.Atan2(-dir.Y, dir.X);
        }
    }
}
